/*
 * This file is part of the Try! Engine project.
 *
 * Copyright 2010-2011 Emanuele Bertoldi. All rights reserved.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * You should have received a copy of the modified BSD License along with this
 * program. If not, see <http://www.opensource.org/licenses/bsd-license.php>
 */

#include "scaletool.h"
#include <projectmodellist.h>
#include <cameranode.h>
#include <scenetransformable.h>
#include <QtGui/QMouseEvent>
#include <QtGui/QMainWindow>
#include <QtGui/QStatusBar>

using namespace Try;

ScaleTool::ScaleTool(QObject* parent)
    :   SelectionTool(parent),
        m_gizmo(0)
{
    this->setName(tr("Scale"));
    this->setIcon("../../data/icons/scale.png");
}

ScaleTool::~ScaleTool()
{
    delete m_gizmo;
}

bool ScaleTool::eventFilter(QObject* watched, QEvent* evt)
{
    bool result = SelectionTool::eventFilter(watched, evt);

    if (watched && watched == this->targetView() && this->isActive())
    {
        switch (evt->type())
        {
            case QEvent::MouseButtonPress:
            {
                QMouseEvent* mouse_evt = static_cast<QMouseEvent*>(evt);
                Project* project = ProjectModelList::instance()->projectAt(0);

                if (mouse_evt && project && mouse_evt->buttons() == Qt::LeftButton)
                {
                    View3d* view3d = this->targetView();

                    QPoint mpos = mouse_evt->pos();

                    // Normalize coordinates.
                    float x = mpos.x() / (float)view3d->width();
                    float y = (view3d->height() - mpos.y()) / (float)view3d->height();

                    if (view3d && view3d->activeCamera())
                        m_startPos = view3d->activeCamera()->projectToWorld(x, y);
                }
            }
            break;

            case QEvent::MouseButtonRelease:
            {
                QMainWindow* main = qobject_cast<QMainWindow*>(this->targetView()->parentWidget());
                if (main)
                    main->statusBar()->clearMessage();

                m_startPos = Vector3::Zero;
            }
            break;

            case QEvent::MouseMove:
            {
                QMouseEvent* mouse_evt = static_cast<QMouseEvent*>(evt);
                Project* project = ProjectModelList::instance()->projectAt(0);

                if (mouse_evt && project && mouse_evt->buttons() == Qt::LeftButton)
                {
                    View3d* view3d = this->targetView();

                    if (view3d && view3d->activeCamera())
                    {
                        QPoint mpos = mouse_evt->pos();

                        // Normalize coordinates.
                        float x = mpos.x() / (float)view3d->width();
                        float y = (view3d->height() - mpos.y()) / (float)view3d->height();

                        Vector3 pos = view3d->activeCamera()->projectToWorld(x, y);

                        Vector3 movement = pos-m_startPos;
                        m_startPos = pos;

                        m_gizmo->m_size += movement;

                        foreach (Object* obj, project->selectedObjects())
                        {
                            Try::SceneTransformable* transform = obj->property<Try::SceneTransformable>();
                            if (transform)
                                transform->resize(movement);
                        }

                        QMainWindow* main = qobject_cast<QMainWindow*>(view3d->parentWidget());
                        if (main)
                        {
                            QString msg = tr("X: %1 | Y: %2 | Z: %3")
                                .arg(QString::number(m_gizmo->m_size.x, 'f', 3))
                                .arg(QString::number(m_gizmo->m_size.y, 'f', 3))
                                .arg(QString::number(m_gizmo->m_size.z, 'f', 3));

                            main->statusBar()->showMessage(msg);
                        }
                    }
                }
            }
            break;

            default:
                break;
        }
    }

    return result;
}

void ScaleTool::onActivationChanged()
{
    SelectionTool::onActivationChanged();

    if (this->isActive() && !m_gizmo)
        m_gizmo = new ScaleGizmo();
}

void ScaleTool::onProjectSelectionChanged(Project* project)
{
    SelectionTool::onProjectSelectionChanged(project);

    if (m_gizmo && m_selectionBox)
    {
        m_gizmo->m_center = m_selectionBox->m_center;
        m_gizmo->m_size = m_selectionBox->m_size;
        m_gizmo->setVisible(this->isActive() && project->selectedObjects().size() > 0);
    }
}
